package org.scboy.gateway.filters;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.web.server.ServerWebExchange;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 异常处理
 */
@Configuration
public class ExceptionFilter implements Ordered, GlobalFilter {

	Log log=LogFactory.get();
	
    /**
     * 如果需要拦截返回值并处理，这里则需要返回负数
     */
    @Override
    public int getOrder() {
        return -800;
    }

    /**
     * 异常拦截，拦截响应值不是 200 的数据，并抛给全局异常处理
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse response = exchange.getResponse();
        ServerHttpResponseDecorator decorated = new ServerHttpResponseDecorator(response) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                    return super.writeWith(fluxBody.map(dataBuffer -> {
                    	
                        if (response.getStatusCode() == HttpStatus.NOT_FOUND) {
                        	
                        	//404返回消息
    						byte[] data=new byte[0];
                        	Map<String, Object> result=new HashMap<String, Object>();
							result.put("status", 404);
							result.put("success", false);
							result.put("message", "找不到请求资源。");
							try {
								data = new ObjectMapper().writeValueAsBytes(result);
							} catch (JsonProcessingException e) {
								log.error(e);
							}
                            DataBufferUtils.release(dataBuffer); // 释放掉内存
							return bufferFactory().wrap(data);
                        }else if (response.getStatusCode() != HttpStatus.OK) {
                            byte[] content = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(content);
                            DataBufferUtils.release(dataBuffer); // 释放掉内存
                            String errMsg = new String(content, StandardCharsets.UTF_8);
							log.error(errMsg);
							
                            byte[] data=new byte[0];
                            
                            //异常返回消息。
                        	Map<String, Object> result=new HashMap<String, Object>();
							result.put("status", 500);
							result.put("success", false);
							result.put("message", "请求无法到达，请联系管理员。");
							try {
								data = new ObjectMapper().writeValueAsBytes(result);
							} catch (JsonProcessingException e) {
							}
							return bufferFactory().wrap(data);
                        }else {
                            return dataBuffer;
                        }
                    }));
                }
                return super.writeWith(body);
            }
        };
        return chain.filter(exchange.mutate().response(decorated).build());
    }
}
